// 素描算法
function make_sketch(base_data, base_width, base_height, return_data, return_width, return_height, blurSize, threshMin) {
  // console.log(base_data.length, base_width*base_height*4, return_data.length, return_width * return_height * 4)
  // console.log(base_width, base_height, return_width, return_height)
  // 依据 base_data 计算素描结果
  // blur_size 要跟着图像尺寸变
  // let blurSize = Math.max(3, Math.min(9, Math.max(base_width / 200, base_height / 200)));
  // blurSize = Math.floor(blurSize) | 1; // 取整数并转为奇数（偶数加1）
  // const blurSize = 17
  const sketch_data = do_sketch_process(base_data, base_width, base_height, blurSize, threshMin, 1.0)
  // resize 到 return_data 的尺寸
  // 1. 创建一个中转离屏 canvas
  const offscreen = wx.createOffscreenCanvas({ type: '2d' });
  offscreen.width = base_width;
  offscreen.height = base_height;
  const offCtx = offscreen.getContext('2d');
  // 2. 创建 imageData 并填充帧数据
  const imageData = offCtx.createImageData(base_width, base_height);
  imageData.data.set(sketch_data);
  offCtx.putImageData(imageData, 0, 0);

   // 3. 创建目标 canvas（缩放目标尺寸）
   const resizedCanvas = wx.createOffscreenCanvas({ type: '2d' });
   resizedCanvas.width = return_width;
   resizedCanvas.height = return_height;
   const resizedCtx = resizedCanvas.getContext('2d');
   // 4. 缩放绘制到目标 canvas
   resizedCtx.drawImage(offscreen, 0, 0, return_width, return_height);
   // 5. 从目标 canvas 提取缩放后的像素数据
   const resizedImageData = resizedCtx.getImageData(0, 0, return_width, return_height);
   return_data.set(resizedImageData.data);
    
   // 主动资源释放
  // offscreen = null;
  // resizedCanvas = null;
  // offCtx = null;
  // resizedCtx = null;
  // imageData = null;
  // resizedImageData = null;
}

function do_sketch_process(data, width, height, blurSize = 9, threshMin = 0.0, threshMax = 1.0) {
  const length = width * height;
  if (!do_sketch_process._gray || do_sketch_process._gray.length !== length) {
    do_sketch_process._gray = new Float32Array(length);
  } else {
    do_sketch_process._gray.fill(0);
  }  
  const gray = do_sketch_process._gray

  // 1. 预处理：转灰度并归一化
  for (let i = 0; i < length; i++) {
    const idx = i * 4;
    const r = data[idx];
    const g = data[idx + 1];
    const b = data[idx + 2];
    gray[i] = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
  }

  // 2. 高斯模糊
  const sigma = blurSize / 6;
  const kernel = gaussianKernel(blurSize, sigma);
  const blurred = applyGrayConvolution(gray, width, height, kernel); // 返回 Float32Array

  const eps = 0.01;
  
  if (!do_sketch_process._outData || do_sketch_process._outData.length !== length) {
    do_sketch_process._outData = new Uint8ClampedArray(length * 4);
  } else {
    do_sketch_process._outData.fill(0);
  }  
  const outData = do_sketch_process._outData

  // 3. 逐像素计算增强
  for (let i = 0; i < length; i++) {
    let val = (gray[i] + eps) / (blurred[i] + eps);
    val = Math.min(threshMax, Math.max(threshMin, val));
    val = (val - threshMin) / (threshMax - threshMin);
    const finalVal = Math.floor(val * 255);

    const idx = i * 4;
    outData[idx] = finalVal;
    outData[idx + 1] = finalVal;
    outData[idx + 2] = finalVal;
    outData[idx + 3] = 255; // 设置为不透明
  }

  return outData;
}

function gaussianKernel(size, sigma) {
  const kernel = [];
  const mean = Math.floor(size / 2);
  let sum = 0;
  for (let x = 0; x < size; x++) {
    kernel[x] = [];
    for (let y = 0; y < size; y++) {
      const ex = Math.exp(-0.5 * (Math.pow((x - mean) / sigma, 2) + Math.pow((y - mean) / sigma, 2)));
      kernel[x][y] = ex;
      sum += ex;
    }
  }
  // Normalize
  for (let x = 0; x < size; x++) {
    for (let y = 0; y < size; y++) {
      kernel[x][y] /= sum;
    }
  }
  return kernel;
}

function applyGrayConvolution(grayData, width, height, kernel) {
  const kSize = kernel.length;
  const kHalf = Math.floor(kSize / 2);
  if (!applyGrayConvolution._output || applyGrayConvolution._output.length !== width * height) {
    applyGrayConvolution._output = new Float32Array(width * height);
  } else {
    applyGrayConvolution._output.fill(0);
  }  
  const output = applyGrayConvolution._output 

  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      let sum = 0;
      for (let ky = 0; ky < kSize; ky++) {
        for (let kx = 0; kx < kSize; kx++) {
          const px = Math.min(width - 1, Math.max(0, x + kx - kHalf));
          const py = Math.min(height - 1, Math.max(0, y + ky - kHalf));
          const idx = py * width + px;
          sum += grayData[idx] * kernel[ky][kx];
        }
      }
      output[y * width + x] = sum;
    }
  }
  return output;
}

// 图片素描处理函数
const processImageToSketch = (imagePath, blurSize, threshMin) => {
  return new Promise((resolve, reject) => {
    // 获取图片信息
    wx.getImageInfo({
      src: imagePath,
      success: (imgInfo) => {
        const { width, height } = imgInfo;
        
        // 创建画布查询
        const query = wx.createSelectorQuery();
        query.select('#sketchCanvas')
          .fields({ node: true, size: true })
          .exec(async (res) => {
            if (!res[0] || !res[0].node) {
              return reject('Canvas not found');
            }
            
            const canvas = res[0].node;
            const ctx = canvas.getContext('2d');
            
            // 设置画布尺寸
            canvas.width = width;
            canvas.height = height;
            
            try {
              // 加载图片
              const img = canvas.createImage();
              img.src = imagePath;
              
              await new Promise((resolve) => {
                img.onload = resolve;
                img.onerror = () => reject('Image load failed');
              });
              
              // 绘制图片
              ctx.clearRect(0, 0, width, height);
              ctx.drawImage(img, 0, 0, width, height);
              
              // 获取图像数据
              const imageData = ctx.getImageData(0, 0, width, height);
              // console.log(blurSize, threshMin)
              make_sketch(imageData.data, width, height, imageData.data, width, height, blurSize, threshMin)
              
              // 回写处理后的数据
              ctx.putImageData(imageData, 0, 0);
              
              // 保存图片到本地
              wx.canvasToTempFilePath({
                canvas: canvas,
                success: (res) => resolve(res.tempFilePath),
                fail: reject
              });
              
            } catch (error) {
              reject(error);
            }
          });
      },
      fail: reject
    });
  });
};



module.exports = {
  // realtimeSketch,
  make_sketch,
  processImageToSketch
};